#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "nvs_flash.h"
#include <stdio.h>
#include "DEV_Config.h"
#include "EPD_4in2.h"
#include "GUI_Paint.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "lwip/err.h"
#include "lwip/apps/sntp.h"
#include "esp_tls.h"
#include "esp_http_client.h"
#include <inttypes.h>
#include "cJSON.h"
#include "icons.h"
#include "jpg.h"
#include <time.h>

/* WiFi配置 */
#define WiFi_STA_SSID "Tenda_16F4C0"
#define WiFi_STA_PASSWORD "804804qwe"
#define WiFi_MAX_RETRY 15

/* 全局变量 */
static EventGroupHandle_t wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1
static const char *TAG = "Main";
char Time_Buff[16] = {0};
char Data_Buff[16] = {0};
char Temp_Buff[16] = {0};
//char Hum_Buff[16] = {0};
UBYTE *BlackImage = NULL;
const tImage* image = NULL;

/* NTP配置 */
#define NTP_SERVER "pool.ntp.org"
#define TIME_ZONE 8  // 东八区

/* 函数声明 */
void update_display(void);
void initialize_sntp(void);
void obtain_time(void);
void time_sync_notification_cb(struct timeval *tv);
void update_time_string(void);
int calculate_days_until_target(void);

/* SNTP时间同步回调 */
void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "Time synchronized");
    update_time_string();
}

/* 初始化SNTP服务 */
void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, NTP_SERVER);
    time_sync_notification_cb(time_sync_notification_cb);
    sntp_init();
}

/* 获取网络时间 */
void obtain_time(void)
{
    initialize_sntp();
    time_t now = 0;
    struct tm timeinfo = {0};
    int retry = 0;
    const int retry_count = 15;
    
    while (timeinfo.tm_year < (2024 - 1900) && ++retry < retry_count) {
        ESP_LOGI(TAG, "等待系统时间同步... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        time(&now);
        localtime_r(&now, &timeinfo);
    }
    
    setenv("TZ", "CST-8", 1);  // 设置时区为东八区
    tzset();
}

/* 更新时间字符串 */
void update_time_string(void)
{
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
    strftime(Time_Buff, sizeof(Time_Buff), "%H:%M", &timeinfo);
    strftime(Data_Buff, sizeof(Data_Buff), "%Y/%m/%d", &timeinfo);
}

/* 计算从今天到 2025-12-20 的剩余天数 */
int calculate_days_until_target(void)
{
    time_t now;
    struct tm target = {0};
    double diff_seconds;
    int diff_days;

    // 获取当前时刻
    time(&now);

    // 构造目标日期：2025‑12‑20 00:00:00
    target.tm_year = 2025 - 1900;
    target.tm_mon  = 12 - 1;
    target.tm_mday = 20;
    target.tm_hour = 0;
    target.tm_min  = 0;
    target.tm_sec  = 0;

    time_t target_time = mktime(&target);
    diff_seconds = difftime(target_time, now);
    diff_days = (int)(diff_seconds / (24 * 3600));

    if (diff_days < 0) diff_days = 0;
    return diff_days;
}

/* HTTP请求处理（天气）*/
static void http_client_task(void *pvParameters)
{
    char output_buffer[2000] = {0};
    static const char *URL = "http://api.seniverse.com/v3/weather/now.json?"
                             "key=Sghh4k6zfmsId_xYm&location=hangzhou"
                             "&language=en&unit=c";
    esp_http_client_config_t config = { 
        .url = URL,
        .buffer_size = sizeof(output_buffer)
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_method(client, HTTP_METHOD_GET);
    if (esp_http_client_open(client, 0) == ESP_OK) {
        int content_length = esp_http_client_fetch_headers(client);
        if (content_length > 0) {
            int read_len = esp_http_client_read_response(client, output_buffer, sizeof(output_buffer));
            if (read_len >= 0) {
                cJSON *root = cJSON_Parse(output_buffer);
                if (root) {
                    cJSON *results = cJSON_GetObjectItem(root, "results");
                    if (results && cJSON_IsArray(results) && cJSON_GetArraySize(results) > 0) {
                        cJSON *first = cJSON_GetArrayItem(results, 0);
                        cJSON *now = cJSON_GetObjectItem(first, "now");
                        if (now) {
                            cJSON *temperature = cJSON_GetObjectItem(now, "temperature");
                            if (temperature && cJSON_IsString(temperature)) {
                                snprintf(Temp_Buff, sizeof(Temp_Buff), "%sC", temperature->valuestring);
                            }
                            cJSON *code = cJSON_GetObjectItem(now, "code");
                            int weather_code = (code && cJSON_IsString(code)) ? atoi(code->valuestring) : 99;
                            switch(weather_code) {
                                case 0:  image = &image_data_daysunny;      break;
                                case 1:  image = &image_data_nightclear;   break;
                                case 4:  image = &image_data_cloudy;        break;
                                case 5: case 6: image = &image_data_daycloudy;   break;
                                case 7: case 8: image = &image_data_nightaltcloudy; break;
                                case 9:  image = &image_data_daycloudy;     break;
                                case 10 ... 20: image = &image_data_rain;    break;
                                case 21 ... 25: image = &image_data_snow;    break;
                                case 30 ... 36: image = &image_data_strongwind; break;
                                default: image = NULL;                      break;
                            }
                        }
                    }
                    cJSON_Delete(root);
                }
            }
        }
    }
    esp_http_client_close(client);
    vTaskDelete(NULL);
}

/* WiFi事件处理 */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                              int32_t event_id, void* event_data)
{
    static uint8_t retry_count = 0;
    if (event_base == WIFI_EVENT) {
        if (event_id == WIFI_EVENT_STA_START) {
            esp_wifi_connect();
        } else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
            if (retry_count++ < WiFi_MAX_RETRY) {
                esp_wifi_connect();
            } else {
                xEventGroupSetBits(wifi_event_group, WIFI_FAIL_BIT);
            }
        }
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        retry_count = 0;
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
        obtain_time();
        xTaskCreate(http_client_task, "http_task", 4096, NULL, 5, NULL);
    }
}

/* WiFi 初始化 */
void wifi_init_sta(void)
{
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WiFi_STA_SSID,
            .password = WiFi_STA_PASSWORD,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
}

/* EPD 显示函数 */
void update_display(void)
{
    Paint_Clear(WHITE);

    // 时间与日期
    update_time_string();
    Paint_DrawString_EN(50, 40, Data_Buff, &Font20, WHITE, BLACK);
    Paint_DrawString_EN(50, 60, Time_Buff, &Font24, WHITE, BLACK);

    // 界面分割线与边框
    Paint_DrawLine(0, 14, 399, 14, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
    Paint_DrawLine(0, 200, 399, 200, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
    Paint_DrawRectangle(1, 1, 399, 299, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
    for (size_t i = 1; i < 7; i++) {
        Paint_DrawLine((400 / 7 * i), 200, (400 / 7 * i), 299, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
    }

    // 作者信息和定位
    Paint_DrawImage(digital_ok, 381, 0, 16, 13);
    Paint_DrawString_EN(2, 2, "author:XuZhongYu", &Font12, WHITE, BLACK);
    Paint_DrawString_EN(226, 2, "phone:17657308019", &Font12, WHITE, BLACK);
    Paint_DrawImage(dingwei, 50, 126, 20, 20);
    Paint_DrawString_EN(75, 130, "hangzhou", &Font16, WHITE, BLACK);

    // 天气
    Paint_DrawImage(image, 50, 85, 40, 40);
    Paint_DrawString_EN(91, 90, Temp_Buff, &Font16, WHITE, BLACK);

    // 倒计时：剩余天数
    int days_left = calculate_days_until_target();
    Paint_DrawImage(daojishi, 250, 30, 144, 120);
    Paint_DrawNum(300, 90, days_left, &Font24, BLACK, WHITE);
// Paint_DrawString_CN(250, 160, "去到你想去的地方!", &Font12CN, BLACK, WHITE);
    // 刷新屏幕
    EPD_4IN2_Display(BlackImage);
    EPD_4IN2_Sleep();
}

/* 主循环任务 */
void main_task(void *pvParameters)
{
    DEV_Gpio_Init();
    EPD_4IN2_Init_Fast();
    EPD_4IN2_Clear();
    UWORD image_size = ((EPD_4IN2_WIDTH % 8 == 0) ? (EPD_4IN2_WIDTH / 8) : (EPD_4IN2_WIDTH / 8 + 1)) * EPD_4IN2_HEIGHT;
    BlackImage = (UBYTE *)malloc(image_size);
    Paint_NewImage(BlackImage, EPD_4IN2_WIDTH, EPD_4IN2_HEIGHT, 0, WHITE);

    while (1) {
        update_display();
        EPD_4IN2_Init_Fast();  
        vTaskDelay(pdMS_TO_TICKS(30000));  // 30 秒刷新
    }
}

void app_main(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }

    wifi_init_sta();
    EventBits_t bits = xEventGroupWaitBits(wifi_event_group,
                                           WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
                                           pdFALSE, pdFALSE, portMAX_DELAY);
    if (bits & WIFI_CONNECTED_BIT) {
        xTaskCreate(main_task, "main_task", 8192, NULL, 5, NULL);
    } else {
        ESP_LOGE(TAG, "WiFi连接失败");
        while (1) vTaskDelay(pdMS_TO_TICKS(1000));
    }
}
